package com.heima.comment.service.impl;

import java.util.*;
import java.util.stream.Collectors;

import com.heima.comment.service.CommentService;
import com.heima.common.exception.CustomException;
import com.heima.feigns.user.UserFeign;
import com.heima.model.comment.dto.CommentDto;
import com.heima.model.comment.dto.CommentLikeDto;
import com.heima.model.comment.dto.CommentSaveDto;
import com.heima.model.comment.pojo.ApComment;
import com.heima.model.comment.pojo.ApCommentLike;
import com.heima.model.comment.vo.ApCommentVo;
import com.heima.model.common.dtos.ResponseResult;
import com.heima.model.common.enums.AppHttpCodeEnum;
import com.heima.model.user.pojo.ApUser;
import com.heima.utils.threadlocal.AppThreadLocalUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Sort;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.stereotype.Service;

@Service
public class CommmentServiceImpl implements CommentService {
    @Autowired
    private UserFeign userFeign;
    @Autowired
    private MongoTemplate mongoTemplate;

    /**
     * 保存评论
     * @param dto
     * @return
     */
    @Override
    public ResponseResult saveComment(CommentSaveDto dto) {
        //1.检查参数
        ApUser user = AppThreadLocalUtils.getUser();
        if (user == null) {
            return ResponseResult.errorResult(AppHttpCodeEnum.NEED_LOGIN);
        }
        //2.远程获取根据id获取登录用户
        user = this.userFeign.findUserById(user.getId());
        if (user == null) {
            throw new CustomException(AppHttpCodeEnum.DATA_NOT_EXIST, "未获取用户信息");
        }
        //3.阿里云文本检测
        //4.保存评论信息
        ApComment apComment = new ApComment();
        apComment.setAuthorId(user.getId());
        apComment.setAuthorName(user.getName());
        apComment.setEntryId(dto.getArticleId().longValue());
        apComment.setType((short) 0);
        apComment.setContent(dto.getContent());
        apComment.setImage(user.getImage());
        apComment.setLikes(0);
        apComment.setReply(0);
        apComment.setFlag((short) 0);
        apComment.setCreatedTime(new Date());
        apComment.setUpdatedTime(new Date());
        this.mongoTemplate.insert(apComment);
        return ResponseResult.okResult(AppHttpCodeEnum.SUCCESS);
    }

    /**
     * 评论点赞
     * @param dto
     * @return
     */
    @Override
    public ResponseResult like(CommentLikeDto dto) {
        //1.检查参数
        ApUser user = AppThreadLocalUtils.getUser();
        if (user == null) {
            return ResponseResult.errorResult(AppHttpCodeEnum.NEED_LOGIN);
        }
        //2.根据评论id查询评论信息
        ApComment apComment = this.mongoTemplate.findById(dto.getCommentId(), ApComment.class);
        if (apComment == null) {
            throw new CustomException(AppHttpCodeEnum.DATA_NOT_EXIST, "评论信息不存在");
        }
        //不能重复点赞
        Query query = Query.query(Criteria.where("authorId").is(user.getId()).and("commentId").is(dto.getCommentId()));
        ApCommentLike apCommentLike = this.mongoTemplate.findOne(query, ApCommentLike.class);

        if (apCommentLike != null && dto.getOperation() == 0) {
            throw new CustomException(AppHttpCodeEnum.DATA_EXIST, "已点赞");
        }
        //3.1如果方式为0代表点赞,点赞数+1
        if (dto.getOperation() == 0) {
            apCommentLike = new ApCommentLike();
            apCommentLike.setAuthorId(user.getId());
            apCommentLike.setCommentId(dto.getCommentId());
            apCommentLike.setOperation((short) 0);
            this.mongoTemplate.save(apCommentLike);
            //评论表点赞数加1
            apComment.setLikes(apComment.getLikes() + 1);
            this.mongoTemplate.save(apComment);
        } else {
            //3.2如果方式为1代表删除点赞,并且点赞数减1
            apComment.setLikes(apComment.getLikes() < 1 ? 0 : apComment.getLikes()-1);
            this.mongoTemplate.save(apComment);  //修改评论
            this.mongoTemplate.remove(query, ApCommentLike.class);
        }
        Map map = new HashMap();  //todo 为什么封装map(行为有关?)
        map.put("likes",apComment.getLikes());
        return ResponseResult.okResult(map);
    }

    /**
     * 查询评论列表
     * @param dto
     * @return
     */
    @Override
    public ResponseResult findByArticleId(CommentDto dto) {
        //1. 检查参数 (id   分页 )
        dto.checkParam();
        List<ApComment> apComments;
        // 查询首页，需要先查询热点评论
        if (dto.getIndex().intValue() == 1) {
            // 先查询热点评论
            Query hotQuery = Query.query(Criteria.where("entryId").is(dto.getArticleId())
                    .and("createdTime").lt(dto.getMinDate()).and("flag").is(1))
                    .with(Sort.by(Sort.Direction.DESC, "likes"))
                    .limit(dto.getSize());
            apComments = mongoTemplate.find(hotQuery, ApComment.class);
            if (apComments != null && apComments.size() > 0) {
                List<ApComment> normalList = getNormalComments(dto, dto.getSize() - apComments.size());
                apComments.addAll(normalList);
            } else {
                apComments = getNormalComments(dto, dto.getSize());
            }
        } else {
            // 查询更多，直接查询普通评论
            apComments = getNormalComments(dto, dto.getSize());
        }
        //3. 判断当前用户是否登录
        ApUser user = AppThreadLocalUtils.getUser();
        if (user == null || apComments == null || apComments.size() == 0) {
            //3.1  如果没登录 直接封装结果返回
            return ResponseResult.okResult(apComments);
        }
        //3.2 如果登录了，查看当前分页中的评论信息，哪些评论点过赞  ApComment - ApCommentVo
        List<String> commentIds = apComments.stream()
                .map(ApComment::getId)
                .collect(Collectors.toList());
        // ApCommentLike ( userId    commentId in  (id1 id2 id3)  )
        // 在当前分页数据下， 登录用户 所点过赞的所有数据
        List<ApCommentLike> apCommentLikes = mongoTemplate.find(Query.query(Criteria.where("authorId")
                .is(user.getId()).and("commentId")
                .in(commentIds)), ApCommentLike.class);
        // 10评论       commentId 3评论 点过赞的评论id
        List<String> likeCommentIds = apCommentLikes.stream().map(ApCommentLike::getCommentId).collect(Collectors.toList());
        List<ApCommentVo> commentVoList = new ArrayList<>();
        apComments.forEach(comment -> {
            ApCommentVo apCommentVo = new ApCommentVo();
            BeanUtils.copyProperties(comment, apCommentVo);
            // 查看当前评论是否被点过赞
            if (likeCommentIds.contains(comment.getId())) {
                apCommentVo.setOperation((short) 0);
            }
            commentVoList.add(apCommentVo);
        });
        return ResponseResult.okResult(commentVoList);

    }

    private List<ApComment> getNormalComments(CommentDto dto, Integer size) {
        Query query = Query.query(Criteria.where("entryId").is(dto.getArticleId())
                .and("createdTime").lt(dto.getMinDate()).and("flag").is(0))
                .with(Sort.by(Sort.Direction.DESC, "createdTime"))
                .limit(size);
        return mongoTemplate.find(query, ApComment.class);
    }
}

